package com.sxbbc.common.core.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.function.common.GetRest;
import com.function.common.RestResponse;
import com.sxbbc.common.basics.exceptions.ThrowJsonException;
import com.sxbbc.common.basics.service.redis.RedisUtilsService;
import com.sxbbc.common.basics.service.solr.entity.Solrpage;
import com.sxbbc.common.basics.utils.calculation.CalcuUtils;
import com.sxbbc.common.basics.utils.date.DateUtil;
import com.sxbbc.common.basics.utils.regular.RpxUtils;
import com.sxbbc.common.basics.utils.statics.DynamicSettingUtils;
import com.sxbbc.common.basics.utils.statics.StaticUtils;
import com.sxbbc.common.core.dto.jz.*;
import com.sxbbc.common.core.entity.jz.*;
import com.sxbbc.common.core.enums.BusinessScopeEnums;
import com.sxbbc.common.core.enums.BusinessTypeEnums;
import com.sxbbc.common.core.enums.ProductStatusEnums;
import com.sxbbc.common.core.enums.ProductTypeEnums;
import com.sxbbc.common.core.mapper.jz.*;
import com.sxbbc.common.core.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sxbbc.common.core.service.system.solr.SolrproductService;
import com.sxbbc.common.core.service.system.solr.entity.SolrProductDto;
import com.sxbbc.common.core.utils.BasePage;
import com.sxbbc.common.core.utils.DescartesUtil;
import com.sxbbc.common.core.utils.ProcToSolrUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 商品信息主表 服务实现类
 * </p>
 *
 * @author leehao
 * @since 2019-05-24
 */
@SuppressWarnings("all")
@Service
public class ProcMainServiceImpl extends ServiceImpl<ProcMainMapper, ProcMain> implements IProcMainService {

    @Autowired
    private ProcMainMapper procMainMapper;
    @Autowired
    private ProSkuDetailMapper proSkuDetailMapper;
    @Autowired
    private BBusinessMapper bBusinessMapper;
    @Autowired
    private ProcEvaluateMapper procEvaluateMapper;
    @Autowired
    private AddressMapper addressMapper;
    @Autowired
    private ActivitySeckillMapper activitySeckillMapper;
    @Autowired
    private ActivitySeckillDetailMapper activitySeckillDetailMapper;
    @Autowired
    private BBusinessService bBusinessService;
    @Autowired
    private IAppHomeRecommendService recommendService;
    @Autowired
    private IProcDescribeService procDescribeService;
    @Autowired
    private IProGroupConfigService proGroupConfigService;
    @Autowired
    private IProSkuDetailService proSkuDetailService;
    @Autowired
    private IBExpConfigService bExpConfigService;
    @Autowired
    private IProcFirstClassifyMainService firstClassifyMainService;
    @Autowired
    private IProcSecondClassifyMainService secondClassifyMainService;
    @Autowired
    private IProcThirdClassifyMainService thirdClassifyMainService;
    @Autowired
    private IProcFirstClassifyShopService firstClassifyShopService;
    @Autowired
    private IProcSecondClassifyShopService secondClassifyShopService;
    @Autowired
    private IProcThirdClassifyShopService thirdClassifyShopService;
    @Autowired
    private SolrproductService solrProductService;
    @Autowired
    private IProcInterestService procInterestService;
    @Autowired
    private IActivityRedPacketService activityRedPacketService;
    @Autowired
    private ICCollectProService collectProService;
    @Autowired
    private ICCollectBusService collectBusService;
    @Autowired
    private ICCustomerService cCustomerService;
    @Autowired
    private IActivitySeckillService activitySeckillService;
    @Autowired
    private IActivitySeckillDetailService activitySeckillDetailService;
    @Autowired
    private ICFootprintInfoService footprintInfoService;
    @Autowired
    private RedisUtilsService redisUtilsService;

    /**
     * 商品批量上架
     */
    private static final Integer PRODUCT_SHELVES = 1;
    /**
     * 商品批量下架
     */
    private static final Integer PRODUCT_UNSHELVES = 2;
    /**
     * 商品批量审核
     */
    private static final Integer PRODUCT_CHECK = 3;

    @Override
    public IPage<ProcMain> queryProductList(BasePage<ProcMain> page, ProcMain procMain) {
        QueryWrapper<ProcMain> wrapper = queryWrapper(procMain);
        if (page.isPaging()) {
            super.page(page, wrapper);
        } else {
            List<ProcMain> list = super.list(wrapper);
            page.setRecords(list);
        }
        for (ProcMain p : page.getRecords()) {
            //规格
            QueryWrapper<ProSkuDetail> skuWrapper = new QueryWrapper<ProSkuDetail>();
            skuWrapper.eq("pro_code", p.getProCode()).eq("status", StaticUtils.STATUS_YES);
            p.setProSkuList(proSkuDetailService.list(skuWrapper));
            //商品类型
            p.setProTypeName(ProductTypeEnums.getName(p.getProType()));
            //运费
            if (CalcuUtils.getInstance().isEquals(p.getExpId(), StaticUtils.EXP_FREE)) {
                //运费模板id为0表示免邮
                p.setExpName("包邮");
            } else {
                BExpConfig expConfig = bExpConfigService.getById(p.getExpId());
                if (expConfig != null) {
                    p.setExpName(expConfig.getName());
                } else {
                    p.setExpName("运费模板信息异常");
                }
            }
            BBusiness business = bBusinessMapper.selectById(p.getBid());
            if (business != null && CalcuUtils.getInstance().isEquals(business.getOnOff(), BusinessScopeEnums.ONLINE.getId())) {
                p.setBusinessName(business.getNickNameOn());
            } else {
                p.setBusinessName(business.getNickName());
            }
        }
        return page;
    }

    @Override
    public ProcMain selectOneByProCode(String proCode) {
        QueryWrapper<ProcMain> wrapper = new QueryWrapper<>();
        wrapper.eq("pro_code", proCode);
        return super.getOne(wrapper);
    }

    @Override
    public IPage<AppHomeRecommend> queryRecommendProc(BasePage<AppHomeRecommend> page, ProcMain procMain) {
        IPage<AppHomeRecommend> pageInfo = procMainMapper.queryRecommendProcMain(page, procMain);
        //拿到已被推荐的商品
        List<AppHomeRecommend> recommendList = recommendService.list();
        for (AppHomeRecommend vo : pageInfo.getRecords()) {
            //取创业分
            QueryWrapper<ProSkuDetail> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("pro_code", vo.getProCode());
            List<ProSkuDetail> proSkuDetails = proSkuDetailService.list(queryWrapper);
            vo.setPoint(proSkuDetails.get(0).getPoint());

            for (AppHomeRecommend r : recommendList) {
                //已推荐的设置不可更改
                if (StringUtils.equals(r.getProCode(), vo.getProCode())) {
                    vo.setCheckFlag("checked disabled");
                }
            }
        }
        return pageInfo;
    }

    @Override
    public RestResponse addBusinessProduct(ProcMain procMain, ProductEditVo product) {
        CalcuUtils cal = CalcuUtils.getInstance();
        RpxUtils rpxUtil = RpxUtils.getInstance();
        //获取bid，拿到商家对象的类型，只有自营才允许添加礼包商品
        BBusiness bBusiness = bBusinessService.getById(procMain.getBid());
        if (bBusiness == null) {
            return GetRest.getFail("该商家不存在");
        }
        //商品描述表
        ProcDescribe describe = new ProcDescribe();
        //保存标记
        boolean save = false;
        DateUtil dateUtil = DateUtil.getInstance();
        //商品关键字字段 商品名+商品编码+商品描述
        StringBuffer keyWord = handleGetProductKeyWord(procMain);
        //用于笛卡尔积计算的list
        ArrayList<ArrayList<String>> descartList = new ArrayList<ArrayList<String>>();
        //SKU分组获取到sku名称与sku属性
        //商品规格json字符串处理
        JSONArray specDetail = new JSONArray();
        //得到每组SKU
        String[] skuGroup = product.getSkuDetail().split(",");
        for (String sku : skuGroup) {
            //得到sku的名称与值的数组
            String[] skuOne = sku.split("::");
            JSONObject nameObject = new JSONObject();
            nameObject.put("name", skuOne[0]);
            JSONArray detailArr = new JSONArray();
            //得到sku值的分组
            String[] skuVal = skuOne[1].split("\\^");
            ArrayList<String> skuValList = new ArrayList<>();
            for (String v : skuVal) {
                if (!rpxUtil.verification(v)) {
                    return GetRest.getFail("规格【" + v + "】含有非法字符");
                }
                JSONObject detailObject = new JSONObject();
                detailObject.put("name", v);
                detailArr.add(detailObject);
                skuValList.add(v);
            }
            //sku的JSON字符串
            nameObject.put("detail", detailArr);
            specDetail.add(nameObject);
            //sku值的list，用于笛卡尔积计算
            descartList.add(skuValList);
        }
        //商品sku处理
        //计算笛卡尔积
        ArrayList<String> descartes = DescartesUtil.descartes(descartList);
        String[] stock = product.getStockArr().split(",");
        String[] cost = product.getCostArr().split(",");
        String[] price = product.getPriceArr().split(",");
        String[] skuCode = product.getSkuArr().split(",");
        //String[] skuImg = product.getSkuImg().split(",");
        //用于计算总库存
        int allStock = 0;
        int index = 0;
        for (String sku : descartes) {
            //商品sku详情表
            ProSkuDetail proSku = new ProSkuDetail();
            proSku.setSkuCode(skuCode[index].toUpperCase());
            proSku.setProCode(procMain.getProCode().toUpperCase());
            proSku.setSpecName(sku);
            proSku.setPrice(new BigDecimal(price[index]));
            proSku.setCost(new BigDecimal(cost[index]));
            proSku.setPoint(cal.sub(proSku.getPrice(), proSku.getCost(), 2));  //创业分为出售价-成本价
            proSku.setQty(Integer.parseInt(stock[index]));
            //总库存计算
            allStock = allStock + Integer.parseInt(stock[index]);
            //proSku.setImgUrl(skuImg[index]);
            save = proSkuDetailService.save(proSku);
            index++;
        }
        if (!save) {
            throw new ThrowJsonException("保存商品规格信息失败");
        }
        //商品属性处理 如果该版本需要则进入发放
        if (DynamicSettingUtils.PRODUCT_PROPERTIES_NEED) {
            JSONArray propArr = new JSONArray();
            for (int i = 0; i < product.getProperties().length; i++) {
                JSONObject detailObject = new JSONObject();
                detailObject.put("name", product.getProperties()[i]);
                detailObject.put("value", product.getPropertiesVal()[i]);
                //商品关键词处理
                keyWord.append(",").append(product.getPropertiesVal()[i]);
                propArr.add(detailObject);
            }
            describe.setAttributeDetails(propArr.toString());
        }
        //保存商品描述信息
        describe.setProCode(procMain.getProCode());
        describe.setSpecDetails(specDetail.toString());
        describe.setPcDetails(product.getPcDetail());
        //如果不是特殊情况，appDetails与pc一致
        describe.setAppDetails(product.getPcDetail());
        save = procDescribeService.save(describe);
        if (!save) {
            throw new ThrowJsonException("保存商品描述信息失败");
        }
        //总库存
        procMain.setQty(allStock);
        //价格默认为第一组价格
        procMain.setPrice(new BigDecimal(price[0]));
        procMain.setKeyWords(keyWord.toString());
        //保存商品
        save = super.save(procMain);
        if (!save) {
            throw new ThrowJsonException("保存商品信息失败");
        }
        return GetRest.getSuccess("保存成功");
    }

    @Override
    public RestResponse handleProductStatus(ProcMain procMain) {
        ProcMain proc = super.getById(procMain);
        if (proc == null) {
            return GetRest.getFail("该商品不存在！");
        }
        CalcuUtils cal = CalcuUtils.getInstance();
        boolean update = false;
        RestResponse solrResult = null;
        //如果处理商品上架
        if (procMain.getStatus() != null) {
            //查询已售库存
            Integer saleQty = procMainMapper.queryProcSaleQty(proc.getProCode());
            if (cal.isEquals(procMain.getStatus(), ProductStatusEnums.SHELVES.getId())) {
                if (procMain.getExamineStatus() == null && !cal.isEquals(proc.getExamineStatus(), StaticUtils.STATUS_YES)) {
                    return GetRest.getFail("该商品还未审核通过,不能进行上架操作！");
                }
                //对商品上架 判断商品原状态是什么状态 更新到solr
                //如果数据库查出来的商品和上架的状态值相等则fail
                if (cal.isEquals(proc.getStatus(), ProductStatusEnums.SHELVES.getId())) {
                    return GetRest.getFail("该商品已经是上架状态！");
                } else {
                    //solr
                    SolrProductDto solrProductDto = ProcToSolrUtil.getSolrProductDto(proc, saleQty);
                    solrResult = solrProductService.addProduct(solrProductDto);
                    if (solrResult != null && solrResult.isStatus()) {
                        //数据库
                        proc.setStatus(procMain.getStatus());
                        proc.setLastShelfTime(new Date());
                    }
                }
            } else if (cal.isEquals(procMain.getStatus(), ProductStatusEnums.UNSHELVES.getId())) {
                //如果商品已经是已下架或者删除的状态
                if (cal.isEquals(proc.getStatus(), ProductStatusEnums.UNSHELVES.getId())) {
                    return GetRest.getFail("该商品已经是所要处理的状态！");
                }
                //商品下架或者删除
                //solr删除
                solrResult = solrProductService.deleteProduct(proc.getProCode());
                if (solrResult != null && solrResult.isStatus()) {
                    //数据库状态变更
                    proc.setStatus(procMain.getStatus());
                }
            } else if (cal.isEquals(procMain.getStatus(), ProductStatusEnums.DELETE.getId())) {
                if (cal.isEquals(proc.getStatus(), ProductStatusEnums.DELETE.getId())) {
                    return GetRest.getFail("该商品已经是所要处理的状态！");
                }
                //商品下架或者删除
                //solr删除
                solrResult = solrProductService.deleteProduct(proc.getProCode());
                if (solrResult != null && solrResult.isStatus()) {
                    //数据库状态变更
                    proc.setStatus(procMain.getStatus());
                }
            }
        }
        //当该版本中商品需要平台审核时 进入此方法
        if (DynamicSettingUtils.PRODUCT_NEED_PLAT_APPLY) {
            if (procMain.getExamineStatus() != null) {
                proc.setExamineStatus(procMain.getExamineStatus());
            }
        }
        //数据库更新
        update = super.updateById(proc);
        if ((solrResult != null && !solrResult.isStatus()) || !update) {
            throw new ThrowJsonException("处理商品状态失败");
        }
        return GetRest.getSuccess("处理成功");
    }

    @Override
    public RestResponse handleProductStatusBatch(Integer type, String[] ids) {
        CalcuUtils cal = CalcuUtils.getInstance();
        List<ProcMain> list = new ArrayList<>();
        RestResponse solrResult = null;
        for (String id : ids) {
            ProcMain proc = super.getById(Integer.parseInt(id));
            if (proc == null) {
                return GetRest.getFail("该商品不存在！");
            }
            Integer saleQty = procMainMapper.queryProcSaleQty(proc.getProCode());
            if (cal.isEquals(type, PRODUCT_SHELVES)) {
                //上架
                //对不是"上架"状态的商品进行操作
                if (!cal.isEquals(proc.getStatus(), ProductStatusEnums.SHELVES.getId())) {
                    SolrProductDto solrProductDto = ProcToSolrUtil.getSolrProductDto(proc, saleQty);
                    solrResult = solrProductService.addProduct(solrProductDto);
                    if (solrResult.isStatus()) {
                        proc.setStatus(ProductStatusEnums.SHELVES.getId());
                        proc.setLastShelfTime(new Date());
                    } else {
                        throw new ThrowJsonException("批量添加商品到搜索缓存失败");
                    }
                }
            } else if (cal.isEquals(type, PRODUCT_UNSHELVES)) {
                //下架
                //对不是"下架"状态的商品进行操作
                if (!cal.isEquals(proc.getStatus(), ProductStatusEnums.UNSHELVES.getId())) {
                    solrResult = solrProductService.deleteProduct(proc.getProCode());
                    if (solrResult.isStatus()) {
                        proc.setStatus(ProductStatusEnums.UNSHELVES.getId());
                    } else {
                        throw new ThrowJsonException("批量从搜索缓存删除商品失败");
                    }
                }
            }
            //该版本商品是否需要平台审核 需要时进入此方法
            if (DynamicSettingUtils.PRODUCT_NEED_PLAT_APPLY) {
                if (cal.isEquals(type, PRODUCT_CHECK)) {
                    //审核
                    proc.setExamineStatus(ProductStatusEnums.HAS_CHECK.getId());
                }
            }
            list.add(proc);
        }
        boolean updateBatch = super.updateBatchById(list);
        if (!updateBatch) {
            throw new ThrowJsonException("批量操作商品状态失败");
        }
        return GetRest.getSuccess("操作成功");
    }

    @Override
    public Solrpage<SolrProductDto> queryProductListBySolr(ProductVo productVo, Integer cpage, SearchVo search) {
        SolrProductDto solrProductDto = new SolrProductDto();
        solrProductDto.setType(ProductTypeEnums.NORMAL.getId());
        CalcuUtils calUtil = CalcuUtils.getInstance();
        //二级分类不为空 存在三级分类
        //主分类就是二级分类ID 三级分类ID=0表示全部，不=0表示三级分类的ID
        if (productVo.getSecondId() != null) {
            if (productVo.getThirdId() != null) {
                //如果三级分类ID=0
                if (calUtil.isEquals(productVo.getThirdId(), StaticUtils.STATUS_NO)) {
                    //根据二级分类ID作为主ID去查询
                    solrProductDto.setSclassid(productVo.getSecondId());
                } else {
                    //三级分类ID不为0，根据三级分类ID去查询
                    solrProductDto.setTclassid(productVo.getThirdId());
                }
            } else {
                //二级分类不为空 不存在三级分类
                //主分类就是二级分类ID 没有三级分类
                solrProductDto.setSclassid(productVo.getSecondId());
            }
        }
        if (StringUtils.isNotBlank(search.getKey())) {
            solrProductDto.setKeyword(search.getKey());
        }
        List<SolrProductDto> returnSolrProductDto = new ArrayList<SolrProductDto>();
        //去solr中根据分类ID查询商品
        Solrpage<SolrProductDto> solrPage = solrProductService.queryProduct(solrProductDto, search.getSortType(), search.getSortDesc(), cpage);
        if (!CollectionUtils.isEmpty(solrPage.getList()) && solrPage.getList().size() > 0) {
            //检查商品的店铺类型属性、红包活动标记
            for (SolrProductDto dto : solrPage.getList()) {
                //设置商品所属商家的店铺类型
                if (calUtil.isEquals(BusinessTypeEnums.OWN_BUSINESS.getId(), bBusinessMapper.getBusinessType(dto.getBid()))) {
                    dto.setbTypeName(BusinessTypeEnums.OWN_BUSINESS.getName());
                }
                BBusiness business = bBusinessMapper.selectById(dto.getBid());
                if (calUtil.isEquals(BusinessScopeEnums.ONLINE.getId(), business.getOnOff())) {
                    returnSolrProductDto.add(dto);
                }
            }
        }
        solrPage.setList(returnSolrProductDto);
        return solrPage;
    }

    @Override
    public IPage<ProcMain> queryDefaultProductList(BasePage<ProcMain> page) {
        return baseMapper.queryNormalCustomerLike(page);
    }

    @Override
    public ProductDetailVo selectProductDetail(ProductVo productVo) {
        ProcMain procMain = this.selectOneByProCode(productVo.getProCode());
        if (procMain == null) {
            throw new ThrowJsonException("商品不存在！");
        }
        /* 店铺信息 */
        BBusiness bBusiness = bBusinessService.getById(procMain.getBid());
        //店铺被收藏数
        QueryWrapper<CCollectBus> busWrapper = new QueryWrapper<>();
        busWrapper.eq("bid", bBusiness.getId()).eq("status", StaticUtils.STATUS_YES);
        bBusiness.setCollect(collectBusService.count(busWrapper));
        //店铺上架的商品数
        QueryWrapper<ProcMain> proNumWrapper = new QueryWrapper<>();
        proNumWrapper.eq("bid", bBusiness.getId()).eq("status", ProductStatusEnums.SHELVES.getId())
                .eq("pro_type", ProductTypeEnums.NORMAL.getId());
        bBusiness.setProNum(super.count(proNumWrapper));
        //计算店铺评分
        //获取总分
        BigDecimal descScore = procEvaluateMapper.getSumScore(bBusiness.getId(), "desc_score");
        BigDecimal serviceScore = procEvaluateMapper.getSumScore(bBusiness.getId(), "service_score");
        BigDecimal expScore = procEvaluateMapper.getSumScore(bBusiness.getId(), "exp_score");
        //获取有效评论数
        Integer count = procEvaluateMapper.countBusiness(bBusiness.getId());
        CalcuUtils calUtil = CalcuUtils.getInstance();
        bBusiness.setDescScore(calUtil.calBusinessScore(descScore, new BigDecimal(count)));
        bBusiness.setServiceScore(calUtil.calBusinessScore(serviceScore, new BigDecimal(count)));
        bBusiness.setExpScore(calUtil.calBusinessScore(expScore, new BigDecimal(count)));
        ProductDetailVo detailVo = new ProductDetailVo();
        detailVo.setPId(procMain.getId());
        if (calUtil.isEquals(bBusiness.getOnOff(), BusinessScopeEnums.ONLINE.getId())) {
            detailVo.setLinkPhone(bBusiness.getPhone());
        } else if (calUtil.isEquals(bBusiness.getOnOff(), BusinessScopeEnums.OFFLINE.getId())) {
            detailVo.setLinkPhone(bBusiness.getLinkPhone());
        }
        detailVo.setProCode(procMain.getProCode());
        detailVo.setProType(procMain.getProType());
        detailVo.setProUrl(procMain.getProImgs());
        if (calUtil.isEquals(bBusiness.getBType(), BusinessTypeEnums.OWN_BUSINESS.getId())) {
            detailVo.setBTypeName(BusinessTypeEnums.OWN_BUSINESS.getName());
        }
        detailVo.setProName(procMain.getProName());
        detailVo.setPrice(procMain.getPrice());

        //店铺
        bBusiness.setPayWord(null);
        bBusiness.setScale(null);
        bBusiness.setCid(null);
        detailVo.setBBusiness(bBusiness);
        /* 运费 */
        if (calUtil.isEquals(procMain.getExpId(), StaticUtils.EXP_FREE)) {
            detailVo.setExpName("包邮");
        } else {
            BExpConfig bExpConfig = bExpConfigService.getById(procMain.getExpId());
            if (bExpConfig != null) {
                detailVo.setExpName(bExpConfig.getName());
            } else {
                detailVo.setExpName("");
            }
        }

        /* 商品权益 */
        List<ProcInterest> interList = null;
        if (StringUtils.isNotBlank(procMain.getInterest())) {
            QueryWrapper<ProcInterest> interWrapper = new QueryWrapper<>();
            interWrapper.in("id", Arrays.asList(procMain.getInterest().split(","))).
                    eq("status", StaticUtils.STATUS_YES);
            interList = procInterestService.list(interWrapper);
        }
        List<String> interestList = new ArrayList<>();
        if (interList != null && !CollectionUtils.isEmpty(interList)) {
            for (ProcInterest i : interList) {
                interestList.add(i.getName());
            }
        }
        //取第一个sku的创业分
        List<ProSkuDetail> skuDetails = proSkuDetailMapper.queryProductDetailList(productVo.getProCode(), bBusiness.getId());
        if (skuDetails.size() > 0) {
            detailVo.setPoint(skuDetails.get(0).getPoint());
        }
        detailVo.setInterList(interestList);
        /* 商品规格 */
        List<PropertiesVo> procSkuList = procDescribeService.getProcSkuList(procMain.getProCode());
        detailVo.setSkuList(procSkuList);
        /* 已售 */
        Integer saleQty = this.baseMapper.queryProcSaleQty(procMain.getProCode());
        detailVo.setSaleQty(saleQty);
        /* 产地 */
        String proName = addressMapper.getAddressName(procMain.getProducePro());
        String cityName = addressMapper.getAddressName(procMain.getProduceCity());
        detailVo.setProducePlace(proName + " " + cityName);
        /* 是否收藏 */
        if (productVo.getCid() != null) {
            procMain.setCid(productVo.getCid());
            QueryWrapper<CCollectPro> collectWrapper = new QueryWrapper<>();
            collectWrapper.eq("cid", productVo.getCid()).eq("pro_code", procMain.getProCode());
            CCollectPro cCollectPro = collectProService.getOne(collectWrapper);
            if (cCollectPro != null) {
                detailVo.setCollectFlag(cCollectPro.getStatus());
            } else {
                detailVo.setCollectFlag(StaticUtils.STATUS_NO);
            }
        }
        /* 评论 页面放单条记录，点进去看列表 */
        QueryWrapper<ProcEvaluate> evaluateWrapper = new QueryWrapper<>();
        evaluateWrapper.orderByDesc("create_time");
        evaluateWrapper.eq("pro_id", procMain.getId()).eq("bid", procMain.getBid());
        List<ProcEvaluate> procEvaluates = procEvaluateMapper.selectList(evaluateWrapper);
        if (!CollectionUtils.isEmpty(procEvaluates) && procEvaluates.size() > 0) {
            ProcEvaluate procEvaluate = procEvaluates.get(0);
            CCustomer cCustomer = cCustomerService.getById(procEvaluate.getCid());
            if (cCustomer != null) {
                procEvaluate.setCHeadUrl(cCustomer.getHeadurl());
                procEvaluate.setCNickName(cCustomer.getNickName());
            }
            List<String> urlList = new ArrayList<>();
            if (StringUtils.isNotBlank(procEvaluate.getEvaluateUrl())) {
                String[] urls = procEvaluate.getEvaluateUrl().split(",");
                for (String url : urls) {
                    urlList.add(url);
                }
            }
            // 是否匿名
            if (calUtil.isEquals(procEvaluate.getHide(), StaticUtils.STATUS_YES)) {
                procEvaluate.setCHeadUrl("");
                procEvaluate.setCNickName(calUtil.replaceHideName(procEvaluate.getCNickName()));
            }
            procEvaluate.setEvaluateUrlList(urlList);
            detailVo.setProcEvaluate(procEvaluate);
        } else {
            detailVo.setProcEvaluate(null);
        }
        //处理浏览接口新增
//        if (productVo.getCid() != null) {
//            footprintInfoService.addFootprint(procMain);
//            //处理redis更新
//            if (calUtil.isEquals(procMain.getProType(), ProductTypeEnums.NORMAL.getId())
//                    && procMain.getMainClassifySecondId() != null) {
//                redisUtilsService.setSecondKey(productVo.getCid().toString(), procMain.getMainClassifySecondId().toString());
//            }
//        }
        return detailVo;
    }

    public ProductDetailVo selectProductSimpleDetail(ProductVo productVo) {
        ProcMain procMain = this.selectOneByProCode(productVo.getProCode());
        if (procMain == null) {
            throw new ThrowJsonException("商品不存在！");
        }
        /* 店铺信息 */
        BBusiness bBusiness = bBusinessService.getById(procMain.getBid());

        CalcuUtils calUtil = CalcuUtils.getInstance();
        ProductDetailVo detailVo = new ProductDetailVo();
        detailVo.setPId(procMain.getId());
        detailVo.setProCode(procMain.getProCode());
        detailVo.setProType(procMain.getProType());
        detailVo.setProUrl(procMain.getProImgs());
        if (calUtil.isEquals(bBusiness.getBType(), BusinessTypeEnums.OWN_BUSINESS.getId())) {
            detailVo.setBTypeName(BusinessTypeEnums.OWN_BUSINESS.getName());
        } else if (calUtil.isEquals(bBusiness.getBType(), BusinessTypeEnums.SETTLED.getId())) {
            detailVo.setBTypeName(BusinessTypeEnums.SETTLED.getName());
        }
        detailVo.setProName(procMain.getProName());
        detailVo.setPrice(procMain.getPrice());
        //非普通商品处理
        List<ProSkuDetail> skuList = proSkuDetailService.querySkuListByProCode(procMain.getProCode());
        //创业分
        detailVo.setPoint(procMain.getPoint());
        //店铺
        bBusiness.setPayWord(null);
        bBusiness.setScale(null);
        bBusiness.setCid(null);
        detailVo.setBBusiness(bBusiness);

        /* 商品权益 */
        List<ProcInterest> interList = null;
        if (StringUtils.isNotBlank(procMain.getInterest())) {
            QueryWrapper<ProcInterest> interWrapper = new QueryWrapper<>();
            interWrapper.in("id", Arrays.asList(procMain.getInterest().split(","))).
                    eq("status", StaticUtils.STATUS_YES);
            interList = procInterestService.list(interWrapper);
        }
        List<String> interestList = new ArrayList<>();
        if (interList != null && !CollectionUtils.isEmpty(interList)) {
            for (ProcInterest i : interList) {
                interestList.add(i.getName());
            }
        }
        detailVo.setInterList(interestList);
        /* 商品规格 */
        List<PropertiesVo> procSkuList = procDescribeService.getProcSkuList(procMain.getProCode());
        detailVo.setSkuList(procSkuList);
        //是否多sku产品
        QueryWrapper<ProSkuDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("pro_code", procMain.getProCode());
        int count = proSkuDetailService.count(queryWrapper);
        if (count == 1) {
            ProSkuDetail skuDetail = proSkuDetailService.getOne(queryWrapper);
            detailVo.setSkuId(skuDetail.getId());
        }

        /* 已售 */
        Integer saleQty = this.baseMapper.queryProcSaleQty(procMain.getProCode());
        detailVo.setSaleQty(saleQty);
        /* 产地 */
        String proName = addressMapper.getAddressName(procMain.getProducePro());
        String cityName = addressMapper.getAddressName(procMain.getProduceCity());
        detailVo.setProducePlace(proName + " " + cityName);

        //处理浏览接口新增
        if (productVo.getCid() != null) {
            footprintInfoService.addFootprint(procMain);
            //处理redis更新
            if (calUtil.isEquals(procMain.getProType(), ProductTypeEnums.NORMAL.getId())
                    && procMain.getMainClassifySecondId() != null) {
                redisUtilsService.setSecondKey(productVo.getCid().toString(), procMain.getMainClassifySecondId().toString());
            }
        }
        return detailVo;
    }

    @Override
    public RestResponse editBusinessProduct(ProcMain proc, ProductEditVo product) {
        RpxUtils rpxUtil = RpxUtils.getInstance();
        CalcuUtils calUtil = CalcuUtils.getInstance();
        BBusiness bBusiness = bBusinessService.getById(proc.getBid());
        if (bBusiness == null) {
            return GetRest.getFail("该商家不存在");
        }
        ProcMain procMain = this.selectOneByProCode(proc.getProCode());
        //保存标记
        boolean save = false;
        DateUtil dateUtil = DateUtil.getInstance();
        //商品关键词
        StringBuffer keyWord = handleGetProductKeyWord(proc);
        //更新商品信息
        procMain.setProName(proc.getProName());
        procMain.setProUnit(proc.getProUnit());
        procMain.setProDesc(proc.getProDesc());
        procMain.setProUrl(proc.getProUrl());
        procMain.setProImgs(proc.getProImgs());
        procMain.setKeyWords(keyWord.toString());
        procMain.setSort(proc.getSort());
        procMain.setIsInvented(proc.getIsInvented());
        procMain.setInventedNum(proc.getInventedNum());
        procMain.setMainClassifyFirstId(proc.getMainClassifyFirstId());
        procMain.setMainClassifySecondId(proc.getMainClassifySecondId());
        procMain.setMainClassifyThirdId(proc.getMainClassifyThirdId());
        procMain.setShopClassifyFirstId(proc.getShopClassifyFirstId());
        procMain.setShopClassifySecondId(proc.getShopClassifySecondId());
        procMain.setShopClassifyThridId(proc.getShopClassifyThridId());
        procMain.setExpId(proc.getExpId());
        procMain.setIsInvoice(proc.getIsInvoice());
        procMain.setIsRefund(proc.getIsRefund());
        procMain.setLabel(proc.getLabel());
        procMain.setInterest(proc.getInterest());
        procMain.setProducePro(proc.getProducePro());
        procMain.setProduceCity(proc.getProduceCity());
        procMain.setCoverUrl(proc.getCoverUrl());
        procMain.setStatus(proc.getStatus());
        procMain.setExamineStatus(proc.getExamineStatus());
        //用于笛卡尔积计算的list
        ArrayList<ArrayList<String>> descartList = new ArrayList<ArrayList<String>>();
        //SKU分组获取到sku名称与sku属性
        //商品规格json字符串处理
        JSONArray specDetail = new JSONArray();
        //得到每组SKU
        String[] skuGroup = product.getSkuDetail().split(",");
        for (String sku : skuGroup) {
            String[] skuOne = sku.split("::");
            JSONObject nameObject = new JSONObject();
            nameObject.put("name", skuOne[0]);
            JSONArray detailArr = new JSONArray();
            //得到sku值的分组
            String[] skuVal = skuOne[1].split("\\^");
            ArrayList<String> skuValList = new ArrayList<>();
            for (String v : skuVal) {
                if (!rpxUtil.verification(v)) {
                    return GetRest.getFail("规格【" + v + "】含有非法字符");
                }
                JSONObject detailObject = new JSONObject();
                detailObject.put("name", v);
                detailArr.add(detailObject);
                skuValList.add(v);
            }
            //sku的JSON字符串
            nameObject.put("detail", detailArr);
            specDetail.add(nameObject);
            descartList.add(skuValList);
        }
        //商品sku处理
        //首先计算笛卡尔积
        ArrayList<String> descartes = DescartesUtil.descartes(descartList);
        String[] stock = product.getStockArr().split(",");
        String[] cost = product.getCostArr().split(",");
        String[] price = product.getPriceArr().split(",");
        String[] skuCode = product.getSkuArr().split(",");
        //总库存
        int allStock = 0;
        int index = 0;
        QueryWrapper<ProSkuDetail> skuWrapper = new QueryWrapper<>();
        skuWrapper.eq("pro_code", procMain.getProCode()).eq("status", StaticUtils.STATUS_YES);
        List<ProSkuDetail> originalSkuList = proSkuDetailService.list(skuWrapper);
        //页面的规格值是否改变 0名称和值均未改变 1值改变(有新增修改)
        if (calUtil.isEquals(product.getValEditStatus(), StaticUtils.STATUS_NO)) {
            //获取到原来的商品描述表
            ProcDescribe oroginal = procDescribeService.selectByProCode(procMain.getProCode());
            //原规格的JSON字符串与现规格的JSON字符串不匹配
            if (!StringUtils.equals(specDetail.toString(), oroginal.getSpecDetails())) {
                //先将原有规格的状态变为0
                originalSkuList.forEach(x -> x.setStatus(StaticUtils.STATUS_NO));
                save = proSkuDetailService.updateBatchById(originalSkuList);
                if (!save) {
                    throw new ThrowJsonException("更新商品详情表失败");
                }
                //生成新的sku
                for (String sku : descartes) {
                    //商品详情表
                    ProSkuDetail proSku = new ProSkuDetail();
                    proSku.setSkuCode(skuCode[index].toUpperCase());
                    proSku.setProCode(procMain.getProCode().toUpperCase());
                    proSku.setSpecName(sku);
                    proSku.setPrice(new BigDecimal(price[index]));
                    proSku.setCost(new BigDecimal(cost[index]));
                    proSku.setPoint(calUtil.sub(proSku.getPrice(), proSku.getCost(), 2));  //创业分为出售价-成本价
                    proSku.setQty(Integer.parseInt(stock[index]));
                    //总库存
                    allStock = allStock + Integer.parseInt(stock[index]);
                    save = proSkuDetailService.save(proSku);
                    index++;
                }
                if (!save) {
                    throw new ThrowJsonException("保存商品规格信息失败");
                }
            } else {
                for (ProSkuDetail proSkuDetail : originalSkuList) {
                    if (StringUtils.equals(skuCode[index].toUpperCase(), proSkuDetail.getSkuCode())) {
                        proSkuDetail.setQty(Integer.parseInt(stock[index]));
                        proSkuDetail.setPrice(new BigDecimal(price[index]));
                        proSkuDetail.setCost(new BigDecimal(cost[index]));
                        proSkuDetail.setPoint(calUtil.sub(proSkuDetail.getPrice(), proSkuDetail.getCost(), 2));  //创业分为出售价-成本价
                        allStock = allStock + Integer.parseInt(stock[index]);
                        index++;
                    }
                    save = proSkuDetailService.updateById(proSkuDetail);
                }
                if (!save) {
                    throw new ThrowJsonException("更新商品规格信息失败");
                }
            }
        } else if (calUtil.isEquals(product.getValEditStatus(), StaticUtils.STATUS_YES)) {
            //先将原有规格的状态变为0
            originalSkuList.forEach(x -> x.setStatus(StaticUtils.STATUS_NO));
            save = proSkuDetailService.updateBatchById(originalSkuList);
            if (!save) {
                throw new ThrowJsonException("更新商品详情表失败");
            }
            //生成新的sku
            for (String sku : descartes) {
                //商品详情表
                ProSkuDetail proSku = new ProSkuDetail();
                proSku.setSkuCode(skuCode[index].toUpperCase());
                proSku.setProCode(procMain.getProCode().toUpperCase());
                proSku.setSpecName(sku);
                proSku.setPrice(new BigDecimal(price[index]));
                proSku.setCost(new BigDecimal(cost[index]));
                proSku.setPoint(calUtil.sub(proSku.getPrice(), proSku.getCost(), 2));  //创业分为出售价-成本价
                proSku.setQty(Integer.parseInt(stock[index]));
                //总库存
                allStock = allStock + Integer.parseInt(stock[index]);
                save = proSkuDetailService.save(proSku);
                index++;
            }
            if (!save) {
                throw new ThrowJsonException("保存商品规格信息失败");
            }
        } else {
            return GetRest.getFail("编辑参数错误！");
        }

        procMain.setPrice(new BigDecimal(price[0]));

        ProcDescribe describe = procDescribeService.selectByProCode(procMain.getProCode());
        //商品属性处理 如果该版本需要 则进入方法
        if (DynamicSettingUtils.PRODUCT_PROPERTIES_NEED) {
            JSONArray propArr = new JSONArray();
            for (int i = 0; i < product.getProperties().length; i++) {
                JSONObject detailObject = new JSONObject();
                detailObject.put("name", product.getProperties()[i]);
                detailObject.put("value", product.getPropertiesVal()[i]);
                propArr.add(detailObject);
            }
            describe.setAttributeDetails(propArr.toString());
        }
        //商品描述表更新
        describe.setSpecDetails(specDetail.toString());
        describe.setPcDetails(product.getPcDetail());
        describe.setAppDetails(product.getPcDetail());
        save = procDescribeService.updateByProCode(describe);
        if (!save) {
            throw new ThrowJsonException("更新商品描述信息失败");
        }
        procMain.setQty(allStock);
        save = super.updateById(procMain);
        if (!save) {
            throw new ThrowJsonException("保存商品信息失败");
        }
        //状态为上架则更新solr
        if (DynamicSettingUtils.PRODUCT_NEED_PLAT_APPLY) {
            if (calUtil.isEquals(proc.getStatus(), ProductStatusEnums.UNSHELVES.getId())) {
                RestResponse restResponse = solrProductService.deleteProduct(procMain.getProCode());
                if (!restResponse.isStatus()) {
                    throw new ThrowJsonException("更新商品搜索缓存失败");
                }
            }
        } else {
            if (calUtil.isEquals(procMain.getStatus(), ProductStatusEnums.SHELVES.getId())) {
                SolrProductDto solrProductDto = solrProductService.selectById(procMain.getProCode());
                Integer saleQty = super.baseMapper.queryProcSaleQty(procMain.getProCode());
                solrProductDto = ProcToSolrUtil.getSolrProductDto(procMain, saleQty);
                RestResponse restResponse = solrProductService.addProduct(solrProductDto);
                if (!restResponse.isStatus()) {
                    throw new ThrowJsonException("更新商品到搜索缓存失败");
                }
            }
        }
        return GetRest.getSuccess("保存成功");
    }

    @Override
    public Boolean handleProductStatusWithDeleteExp(Integer id) {
        boolean update = false;
        QueryWrapper<ProcMain> wrapper = new QueryWrapper<>();
        wrapper.eq("exp_id", id).ne("exp_id", StaticUtils.EXP_FREE);
        List<ProcMain> procList = super.list(wrapper);
        if (!CollectionUtils.isEmpty(procList)) {
            RestResponse result = null;
            for (ProcMain p : procList) {
                result = solrProductService.deleteProduct(p.getProCode());
                if (result != null && result.isStatus()) {
                    p.setStatus(ProductStatusEnums.UNSHELVES.getId());
                    p.setExamineStatus(ProductStatusEnums.NO_CHECK.getId());
                    p.setExpId(null);
                    update = super.updateById(p);
                }
            }
        } else {
            update = true;
        }
        return update;
    }

    /**
     * 商品公用查询条件
     *
     * @param procMain 查询条件
     * @return QueryWrapper对象
     * @author leehao
     */
    private QueryWrapper<ProcMain> queryWrapper(ProcMain procMain) {
        QueryWrapper<ProcMain> wrapper = new QueryWrapper<>();
        wrapper.ne("status", ProductStatusEnums.DELETE.getId());
        if (procMain.getBid() != null) {
            wrapper.eq("bid", procMain.getBid());
        }
        if (StringUtils.isNotBlank(procMain.getProName())) {
            wrapper.like("pro_name", procMain.getProName());
        }
        if (StringUtils.isNotBlank(procMain.getProCode())) {
            wrapper.eq("pro_code", procMain.getProCode());
        }
        if (procMain.getMainClassifyFirstId() != null) {
            wrapper.eq("main_classify_first_id", procMain.getMainClassifyFirstId());
        }
        if (procMain.getMainClassifySecondId() != null) {
            wrapper.eq("main_classify_second_id", procMain.getMainClassifySecondId());
        }
        if (procMain.getMainClassifyThirdId() != null) {
            wrapper.eq("main_classify_third_id", procMain.getMainClassifyThirdId());
        }
        if (procMain.getStatus() != null) {
            wrapper.eq("status", procMain.getStatus());
        }
        if (procMain.getExamineStatus() != null) {
            wrapper.eq("examine_status", procMain.getExamineStatus());
        }
        if (procMain.getProType() != null) {
            wrapper.eq("pro_type", procMain.getProType());
        }
        return wrapper;
    }

    /**
     * 获取商品关键词
     *
     * @param procMain
     * @return java.lang.String
     * @author leehao
     */
    private StringBuffer handleGetProductKeyWord(ProcMain procMain) {
        StringBuffer keyWord = new StringBuffer(procMain.getProName() + "," + procMain.getProCode() + "," + procMain.getProDesc());
        if (procMain.getMainClassifyFirstId() != null) {
            ProcFirstClassifyMain firstMain = firstClassifyMainService.getById(procMain.getMainClassifyFirstId());
            keyWord.append(",").append(firstMain.getName());
        }
        if (procMain.getMainClassifySecondId() != null) {
            ProcSecondClassifyMain secondMain = secondClassifyMainService.getById(procMain.getMainClassifySecondId());
            keyWord.append(",").append(secondMain.getName());
        }
        if (procMain.getMainClassifyThirdId() != null) {
            ProcThirdClassifyMain thirdMain = thirdClassifyMainService.getById(procMain.getMainClassifyThirdId());
            keyWord.append(",").append(thirdMain.getName());
        }
        if (procMain.getShopClassifyFirstId() != null) {
            ProcFirstClassifyShop firstShop = firstClassifyShopService.getById(procMain.getShopClassifyFirstId());
            keyWord.append(",").append(firstShop.getName());
        }
        if (procMain.getShopClassifySecondId() != null) {
            ProcSecondClassifyShop secondShop = secondClassifyShopService.getById(procMain.getShopClassifySecondId());
            keyWord.append(",").append(secondShop.getName());
        }
        if (procMain.getShopClassifyThridId() != null) {
            ProcThirdClassifyShop thirdShop = thirdClassifyShopService.getById(procMain.getShopClassifyThridId());
            keyWord.append(",").append(thirdShop.getName());
        }
        return keyWord;
    }

    @Override
    public IPage<ProcMain> queryBusinessProduct(BasePage<ProcMain> page, ProcMain procMain) {
        IPage<ProcMain> pageInfo = baseMapper.queryBusinessProduct(page, procMain);
        return pageInfo;
    }

    @Override
    public IPage<NearBusinessProlVo> queryNearBusinessProductList(BasePage<ProcMain> page, Integer bid, Integer firstId) {
        ProcMain procMain = new ProcMain();
        procMain.setStatus(ProductStatusEnums.SHELVES.getId());
        procMain.setExamineStatus(ProductStatusEnums.HAS_CHECK.getId());
        procMain.setProType(ProductTypeEnums.NORMAL.getId());
        procMain.setBid(bid);
        if (firstId != null) {
            procMain.setShopClassifyFirstId(firstId);
        }
        procMain.setExamineStatus(ProductStatusEnums.HAS_CHECK.getId());
        procMain.setStatus(ProductStatusEnums.SHELVES.getId());
        IPage<ProcMain> pageInfo = null;
        try {
            pageInfo = queryBusinessProduct(page, procMain);
        } catch (Exception e) {
            e.printStackTrace();
        }
        List<NearBusinessProlVo> list = new ArrayList<>();
        if (!CollectionUtils.isEmpty(pageInfo.getRecords())) {
            for (ProcMain p : pageInfo.getRecords()) {
                /* 已售 */
                Integer saleQty = procMainMapper.queryProcSaleQty(procMain.getProCode());
                p.setSaleQty(saleQty + p.getInventedNum());
                //是否多sku产品
                QueryWrapper<ProSkuDetail> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("pro_code", p.getProCode());
                List<ProSkuDetail> proSkuDetails = proSkuDetailService.list(queryWrapper);
                if (proSkuDetails.size() == 1) {
                    p.setSkuId(proSkuDetails.get(0).getId());

                }
                p.setPoint(proSkuDetails.get(0).getPoint());
                NearBusinessProlVo vo = new NearBusinessProlVo();
                BeanUtils.copyProperties(p, vo);
                /* 商品规格 */
                List<PropertiesVo> procSkuList = procDescribeService.getProcSkuList(p.getProCode());
                vo.setSkuList(procSkuList);
                list.add(vo);
            }
        }
        BasePage<NearBusinessProlVo> basePage = new BasePage<>();
        basePage.setRecords(list);
        basePage.setCurrent(pageInfo.getCurrent());
        return basePage;
    }
}
